// STL
#include <algorithm>               // std::min_element
#include <iterator>                // std::begin, std::end
#include <stdexcept>               // std::invalid_argument()
#include <vector>                  // std::vector

// jScience
#include "jScience/stats/data.hpp" // partition_data()
#include "jstats.hpp"   // sum()

// stats++
#include "statsxx/dataset/DataSet.hpp" // DataSet


//
// DESC: Partitions a DataSet object.
//
// INPUT:
//     DataSet dataset       : Data set to be partitioned
//     std::vector<double> f : Partition fractions [default of 80/20 for (training and validation)/testing, and 80/20 training/validation of the remaining]
//
// OUTPUT:
//     std::vector<DataSet> return_data_sets : Return data sets, partitioned according to f.
//
// NOTES:
//     ! f is normalized in partition_data(), it need not sum to 1, as passed.
//
inline std::vector<DataSet> partition_data_set( const DataSet &data_set, const std::vector<double> f )
{
/*
    // << JMM: these checks are actually identical to those in partition_data(), so are not done here >>
    if( *std::min_element( std::begin(f), std::end(f) ) < 0.0 )
    {
        throw std::invalid_argument( "partition_dataset(): Received request for a negative partition" );
    }

    if( sum(f) <= 0.0 )
    {
        throw std::invalid_argument( "partition_dataset(): Sum of partitions is <= 0.0" );
    }

    //=========================================================
*/

    std::vector<DataSet> return_data_sets( f.size() );

    std::vector<std::vector<DataPoint>> pts = partition_data( data_set.pt, f );

    for( int i = 0; i < f.size(); ++i )
    {
        return_data_sets[i].pt = pts[i];
    }

    return return_data_sets;
}
